home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / TURB_VIS / TVG121 / TVDEMO.PAS < prev    next >
Pascal/Delphi Source File  |  1994-05-27  |  19KB  |  706 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Vision Demo                            }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. program TVDemo;
  9.  
  10. {$X+,S-}
  11. {$M 16384,8192,655360}
  12.  
  13. { Turbo Vision demo program. This program uses many of the Turbo
  14.   Vision standard and demo units, including:
  15.  
  16.     StdDlg    - Open file browser, change directory tree.
  17.     MsgBox    - Simple dialog to display messages.
  18.     ColorSel  - Color customization.
  19.     Gadgets   - Shows system time and available heap space.
  20.     AsciiTab  - ASCII table.
  21.     Calendar  - View a month at a time
  22.     Calc      - Desktop calculator.
  23.     HelpFile  - Context sensitive help.
  24.     MouseDlg  - Mouse options dialog.
  25.     Puzzle    - Simple brain puzzle.
  26.     Editors   - Text Editor object.
  27.  
  28.   And of course this program includes many standard Turbo Vision
  29.   objects and behaviors (menubar, desktop, status line, dialog boxes,
  30.   mouse support, window resize/move/tile/cascade).
  31. }
  32.  
  33. uses
  34.   TvGraph, Styx,                     { ** TVGRAPH ** }
  35.   Dos, Objects, Drivers, Memory, Views, Menus, Dialogs, StdDlg, HistList,
  36.   MsgBox, App, DemoCmds, Gadgets, Puzzle, Calendar, AsciiTab, Calc,
  37.   HelpFile, DemoHelp, ColorSel, MouseDlg, Editors;
  38.  
  39. { If you get a FILE NOT FOUND error when compiling this program
  40.   from a DOS IDE, change to the \BP\EXAMPLES\DOS\TVDEMO directory
  41.   (use File|Change dir).
  42.  
  43.   This will enable the compiler to find all of the units used by
  44.   this program.
  45. }
  46.  
  47. const
  48.   HeapSize = 48 * (1024 div 16);  { Save 48k heap for main program }
  49.  
  50.   { Desktop file signature information }
  51.   SignatureLen = 21;
  52.   DSKSignature : string[SignatureLen] = 'TV Demo Desktop File'#26;
  53.  
  54. var
  55.   ClipWindow: PEditWindow;
  56.  
  57. type
  58.  
  59.   { TTVDemo }
  60.  
  61.   PTVDemo = ^TTVDemo;
  62.   TTVDemo = object(gApp)                   { ** TVGRAPH ** }
  63.     Clock: PClockView;
  64.     Heap: PHeapView;
  65.     constructor Init;
  66.     procedure FileOpen(WildCard: PathStr);
  67.     function OpenEditor(FileName: FNameStr; Visible: Boolean): PEditWindow;
  68.     procedure GetEvent(var Event: TEvent); virtual;
  69.     function GetPalette: PPalette; virtual;
  70.     procedure Idle; virtual;
  71.     procedure HandleEvent(var Event: TEvent); virtual;
  72.     procedure InitMenuBar; virtual;
  73.     procedure InitStatusLine; virtual;
  74.     procedure LoadDesktop(var S: TStream);
  75.     procedure OutOfMemory; virtual;
  76.     procedure StoreDesktop(var S: TStream);
  77.   end;
  78.  
  79. { CalcHelpName }
  80.  
  81. function CalcHelpName: PathStr;
  82. var
  83.   EXEName: PathStr;
  84.   Dir: DirStr;
  85.   Name: NameStr;
  86.   Ext: ExtStr;
  87. begin
  88.   if Lo(DosVersion) >= 3 then EXEName := ParamStr(0)
  89.   else EXEName := FSearch('TVDEMO.EXE', GetEnv('PATH'));
  90.   FSplit(EXEName, Dir, Name, Ext);
  91.   if Dir[Length(Dir)] = '\' then Dec(Dir[0]);
  92.   CalcHelpName := FSearch('DEMOHELP.HLP', Dir);
  93. end;
  94.  
  95. function CreateFindDialog: PDialog;
  96. var
  97.   D: PDialog;
  98.   Control: PView;
  99.   R: TRect;
  100. begin
  101.   R.Assign(0, 0, 38, 12);
  102.   D := New(PDialog, Init(R, 'Find'));
  103.   with D^ do
  104.   begin
  105.     Options := Options or ofCentered;
  106.  
  107.     R.Assign(3, 3, 32, 4);
  108.     Control := New(PInputLine, Init(R, 80));
  109.     Insert(Control);
  110.     R.Assign(2, 2, 15, 3);
  111.     Insert(New(PLabel, Init(R, '~T~ext to find', Control)));
  112.     R.Assign(32, 3, 35, 4);
  113.     Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
  114.  
  115.     R.Assign(3, 5, 35, 7);
  116.     Insert(New(PCheckBoxes, Init(R,
  117.       NewSItem('~C~ase sensitive',
  118.       NewSItem('~W~hole words only', nil)))));
  119.  
  120.     R.Assign(14, 9, 24, 11);
  121.     Insert(New(PButton, Init(R, 'O~K~', cmOk, bfDefault)));
  122.     Inc(R.A.X, 12); Inc(R.B.X, 12);
  123.     Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  124.  
  125.     SelectNext(False);
  126.   end;
  127.   CreateFindDialog := D;
  128. end;
  129.  
  130. function CreateReplaceDialog: PDialog;
  131. var
  132.   D: PDialog;
  133.   Control: PView;
  134.   R: TRect;
  135. begin
  136.   R.Assign(0, 0, 40, 16);
  137.   D := New(PDialog, Init(R, 'Replace'));
  138.   with D^ do
  139.   begin
  140.     Options := Options or ofCentered;
  141.  
  142.     R.Assign(3, 3, 34, 4);
  143.     Control := New(PInputLine, Init(R, 80));
  144.     Insert(Control);
  145.     R.Assign(2, 2, 15, 3);
  146.     Insert(New(PLabel, Init(R, '~T~ext to find', Control)));
  147.     R.Assign(34, 3, 37, 4);
  148.     Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
  149.  
  150.     R.Assign(3, 6, 34, 7);
  151.     Control := New(PInputLine, Init(R, 80));
  152.     Insert(Control);
  153.     R.Assign(2, 5, 12, 6);
  154.     Insert(New(PLabel, Init(R, '~N~ew text', Control)));
  155.     R.Assign(34, 6, 37, 7);
  156.     Insert(New(PHistory, Init(R, PInputLine(Control), 11)));
  157.  
  158.     R.Assign(3, 8, 37, 12);
  159.     Insert(New(PCheckBoxes, Init(R,
  160.       NewSItem('~C~ase sensitive',
  161.       NewSItem('~W~hole words only',
  162.       NewSItem('~P~rompt on replace',
  163.       NewSItem('~R~eplace all', nil)))))));
  164.  
  165.     R.Assign(17, 13, 27, 15);
  166.     Insert(New(PButton, Init(R, 'O~K~', cmOk, bfDefault)));
  167.     R.Assign(28, 13, 38, 15);
  168.     Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  169.  
  170.     SelectNext(False);
  171.   end;
  172.   CreateReplaceDialog := D;
  173. end;
  174.  
  175. function DoEditDialog(Dialog: Integer; Info: Pointer): Word; far;
  176. var
  177.   R: TRect;
  178.   T: TPoint;
  179. begin
  180.   case Dialog of
  181.     edOutOfMemory:
  182.       DoEditDialog := MessageBox('Not enough memory for this operation.',
  183.         nil, mfError + mfOkButton);
  184.     edReadError:
  185.       DoEditDialog := MessageBox('Error reading file %s.',
  186.         @Info, mfError + mfOkButton);
  187.     edWriteError:
  188.       DoEditDialog := MessageBox('Error writing file %s.',
  189.         @Info, mfError + mfOkButton);
  190.     edCreateError:
  191.       DoEditDialog := MessageBox('Error creating file %s.',
  192.         @Info, mfError + mfOkButton);
  193.     edSaveModify:
  194.       DoEditDialog := MessageBox('%s has been modified. Save?',
  195.         @Info, mfInformation + mfYesNoCancel);
  196.     edSaveUntitled:
  197.       DoEditDialog := MessageBox('Save untitled file?',
  198.         nil, mfInformation + mfYesNoCancel);
  199.     edSaveAs:
  200.       DoEditDialog := Application^.ExecuteDialog(New(PFileDialog, Init('*.*',
  201.         'Save file as', '~N~ame', fdOkButton, 101)), Info);
  202.     edFind:
  203.       DoEditDialog := Application^.ExecuteDialog(CreateFindDialog, Info);
  204.     edSearchFailed:
  205.       DoEditDialog := MessageBox('Search string not found.',
  206.         nil, mfError + mfOkButton);
  207.     edReplace:
  208.       DoEditDialog := Application^.ExecuteDialog(CreateReplaceDialog, Info);
  209.     edReplacePrompt:
  210.       begin
  211.         { Avoid placing the dialog on the same line as the cursor }
  212.         R.Assign(0, 1, 40, 8);
  213.         R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
  214.         Desktop^.MakeGlobal(R.B, T);
  215.         Inc(T.Y);
  216.         if TPoint(Info).Y <= T.Y then
  217.           R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
  218.         DoEditDialog := MessageBoxRect(R, 'Replace this occurence?',
  219.           nil, mfYesNoCancel + mfInformation);
  220.       end;
  221.   end;
  222. end;
  223.  
  224. { TTVDemo }
  225. constructor TTVDemo.Init;
  226. var
  227.   R: TRect;
  228.   I: Integer;
  229.   FileName: PathStr;
  230. begin
  231.   MaxHeapSize := HeapSize;
  232.   inherited Init(smVGA640x480x16 or smUseBGIInterface);
  233.   Prodable:=true;
  234.   RegisterObjects;
  235.   RegisterViews;
  236.   RegisterMenus;
  237.   RegisterDialogs;
  238.   RegisterApp;
  239.   RegisterHelpFile;
  240.   RegisterPuzzle;
  241.   RegisterCalendar;
  242.   RegisterAsciiTab;
  243.   RegisterCalc;
  244.   RegisterEditors;
  245.  
  246.   { Initialize demo gadgets }
  247.  
  248.   GetExtent(R);
  249.   R.A.X := R.B.X - 9; R.B.Y := R.A.Y + 1;
  250.   Clock := New(PClockView, Init(R));
  251.   Insert(Clock);
  252.  
  253.   GetExtent(R);
  254.   Dec(R.B.X);
  255.   R.A.X := R.B.X - 9; R.A.Y := R.B.Y - 1;
  256.   Heap := New(PHeapView, Init(R));
  257.   Insert(Heap);
  258.  
  259.   DisableCommands([cmSave, cmSaveAs, cmCut, cmCopy, cmPaste, cmClear,
  260.     cmUndo, cmFind, cmReplace, cmSearchAgain, cmCloseAll]);
  261.   EditorDialog := DoEditDialog;
  262.   ClipWindow := OpenEditor('', False);
  263.   if ClipWindow <> nil then
  264.   begin
  265.     Clipboard := ClipWindow^.Editor;
  266.     Clipboard^.CanUndo := False;
  267.   end;
  268.  
  269.   for I := 1 to ParamCount do
  270.   begin
  271.     FileName := ParamStr(I);
  272.     if FileName[Length(FileName)] = '\' then
  273.       FileName := FileName + '*.*';
  274.     if (Pos('?', FileName) = 0) and (Pos('*', FileName) = 0) then
  275.       OpenEditor(FExpand(FileName), True)
  276.     else FileOpen(FileName);
  277.   end;
  278. end;
  279.  
  280. function TTVDemo.OpenEditor(FileName: FNameStr; Visible: Boolean): PEditWindow;
  281. var
  282.   P: PView;
  283.   R: TRect;
  284. begin
  285.   DeskTop^.GetExtent(R);
  286.   P := Application^.ValidView(New(PEditWindow,
  287.     Init(R, FileName, wnNoNumber)));
  288.   if not Visible then P^.Hide;
  289.   DeskTop^.Insert(P);
  290.   OpenEditor := PEditWindow(P);
  291. end;
  292.  
  293. procedure TTVDemo.FileOpen(WildCard: PathStr);
  294. var
  295.   FileName: FNameStr;
  296. begin
  297.   FileName := '*.*';
  298.   if ExecuteDialog(New(PFileDialog, Init(WildCard, 'Open a file',
  299.     '~N~ame', fdOpenButton + fdHelpButton, 100)), @FileName) <> cmCancel then
  300.     OpenEditor(FileName, True);
  301. end;
  302.  
  303. procedure TTVDemo.GetEvent(var Event: TEvent);
  304. var
  305.   W: PWindow;
  306.   HFile: PHelpFile;
  307.   HelpStrm: PDosStream;
  308. const
  309.   HelpInUse: Boolean = False;
  310. begin
  311.   inherited GetEvent(Event);
  312.   case Event.What of
  313.     evCommand:
  314.       if (Event.Command = cmHelp) and not HelpInUse then
  315.       begin
  316.         HelpInUse := True;
  317.         HelpStrm := New(PDosStream, Init(CalcHelpName, stOpenRead));
  318.         HFile := New(PHelpFile, Init(HelpStrm));
  319.         if HelpStrm^.Status <> stOk then
  320.         begin
  321.           MessageBox('Could not open help file.', nil, mfError + mfOkButton);
  322.           Dispose(HFile, Done);
  323.         end
  324.         else
  325.         begin
  326.           W := New(PHelpWindow,Init(HFile, GetHelpCtx));
  327.           if ValidView(W) <> nil then
  328.           begin
  329.             ExecView(W);
  330.             Dispose(W, Done);
  331.           end;
  332.           ClearEvent(Event);
  333.         end;
  334.         HelpInUse := False;
  335.       end;
  336.     evMouseDown:
  337.       if Event.Buttons <> 1 then Event.What := evNothing;
  338.   end;
  339. end;
  340.  
  341. function TTVDemo.GetPalette: PPalette;
  342. const
  343.   CNewColor = CAppColor + CHelpColor;
  344.   CNewBlackWhite = CAppBlackWhite + CHelpBlackWhite;
  345.   CNewMonochrome = CAppMonochrome + CHelpMonochrome;
  346.   P: array[apColor..apMonochrome] of string[Length(CNewColor)] =
  347.     (CNewColor, CNewBlackWhite, CNewMonochrome);
  348. begin
  349.   GetPalette := @P[AppPalette];
  350. end;
  351.  
  352. procedure TTVDemo.HandleEvent(var Event: TEvent);
  353.  
  354. procedure ChangeDir;
  355. var
  356.   D: PChDirDialog;
  357. begin
  358.   D := New(PChDirDialog, Init(cdNormal + cdHelpButton, 101));
  359.   D^.HelpCtx := hcFCChDirDBox;
  360.   ExecuteDialog(D, nil);
  361. end;
  362.  
  363. procedure Puzzle;
  364. var
  365.   P: PPuzzleWindow;
  366. begin
  367.   P := New(PPuzzleWindow, Init);
  368.   P^.HelpCtx := hcPuzzle;
  369.   InsertWindow(P);
  370. end;
  371.  
  372. procedure Calendar;
  373. var
  374.   P: PCalendarWindow;
  375. begin
  376.   P := New(PCalendarWindow, Init);
  377.   P^.HelpCtx := hcCalendar;
  378.   InsertWindow(P);
  379. end;
  380.  
  381. procedure About;
  382. var
  383.   D: PDialog;
  384.   Control: PView;
  385.   R: TRect;
  386. begin
  387.   R.Assign(0, 0, 40, 11);
  388.   D := New(PDialog, Init(R, 'About'));
  389.   with D^ do
  390.   begin
  391.     Options := Options or ofCentered;
  392.  
  393.     R.Grow(-1, -1);
  394.     Dec(R.B.Y, 3);
  395.     Insert(New(PStaticText, Init(R,
  396.       #13 +
  397.       ^C'Turbo Vision Demo'#13 +
  398.       #13 +
  399.       ^C'Copyright (c) 1992'#13 +
  400.       #13 +
  401.       ^C'Borland International')));
  402.  
  403.     R.Assign(15, 8, 25, 10);
  404.     Insert(New(PButton, Init(R, 'O~K', cmOk, bfDefault)));
  405.   end;
  406.   if ValidView(D) <> nil then
  407.   begin
  408.     Desktop^.ExecView(D);
  409.     Dispose(D, Done);
  410.   end;
  411. end;
  412.  
  413. procedure AsciiTab;
  414. var
  415.   P: PAsciiChart;
  416. begin
  417.   P := New(PAsciiChart, Init);
  418.   P^.HelpCtx := hcAsciiTable;
  419.   InsertWindow(P);
  420. end;
  421.  
  422. procedure OpenStyx;                      { ** TVGRAPH ** }
  423. var                                      { ** TVGRAPH ** }
  424.   P: PStyxDemo;                          { ** TVGRAPH ** }
  425. begin                                    { ** TVGRAPH ** }
  426.   P := New(PStyxDemo, Init);             { ** TVGRAPH ** }
  427.   P^.HelpCtx := hcNoContext;             { ** TVGRAPH ** }
  428.   Desktop^.Insert(ValidView(P));         { ** TVGRAPH ** }
  429. end;                                     { ** TVGRAPH ** }
  430.  
  431. procedure Calculator;
  432. var
  433.   P: PCalculator;
  434. begin
  435.   P := New(PCalculator, Init);
  436.   P^.HelpCtx := hcCalculator;
  437.   InsertWindow(P);
  438. end;
  439.  
  440. procedure Colors;
  441. var
  442.   D: PColorDialog;
  443. begin
  444.   D := New(PColorDialog, Init('',
  445.     ColorGroup('Desktop',       DesktopColorItems(nil),
  446.     ColorGroup('Menus',         MenuColorItems(nil),
  447.     ColorGroup('Dialogs/Calc',  DialogColorItems(dpGrayDialog, nil),
  448.     ColorGroup('Editor/Puzzle', WindowColorItems(wpBlueWindow, nil),
  449.     ColorGroup('Ascii table',   WindowColorItems(wpGrayWindow, nil),
  450.     ColorGroup('Calendar',
  451.       WindowColorItems(wpCyanWindow,
  452.       ColorItem('Current day',       22, nil)),
  453.       nil))))))));
  454.  
  455.   D^.HelpCtx := hcOCColorsDBox;
  456.  
  457.   if ExecuteDialog(D, Application^.GetPalette) <> cmCancel then
  458.   begin
  459.     DoneMemory;    { Dispose all group buffers }
  460.     ReDraw;        { Redraw application with new palette }
  461.   end;
  462. end;
  463.  
  464. procedure Mouse;
  465. var
  466.   D: PDialog;
  467. begin
  468.   D := New(PMouseDialog, Init);
  469.   D^.HelpCtx := hcOMMouseDBox;
  470.   ExecuteDialog(D, @MouseReverse);
  471. end;
  472.  
  473. procedure RetrieveDesktop;
  474. var
  475.   S: PStream;
  476.   Signature: string[SignatureLen];
  477. begin
  478.   S := New(PBufStream, Init('TVDEMO.DSK', stOpenRead, 1024));
  479.   if LowMemory then OutOfMemory
  480.   else if S^.Status <> stOk then
  481.     MessageBox('Could not open desktop file', nil, mfOkButton + mfError)
  482.   else
  483.   begin
  484.     Signature[0] := Char(SignatureLen);
  485.     S^.Read(Signature[1], SignatureLen);
  486.     if Signature = DSKSignature then
  487.     begin
  488.       LoadDesktop(S^);
  489.       LoadIndexes(S^);
  490.       LoadHistory(S^);
  491.       if S^.Status <> stOk then
  492.         MessageBox('Error reading desktop file', nil, mfOkButton + mfError);
  493.     end
  494.     else
  495.       MessageBox('Error: Invalid Desktop file.', nil, mfOkButton + mfError);
  496.   end;
  497.   Dispose(S, Done);
  498. end;
  499.  
  500. procedure SaveDesktop;
  501. var
  502.   S: PStream;
  503.   F: File;
  504. begin
  505.   S := New(PBufStream, Init('TVDEMO.DSK', stCreate, 1024));
  506.   if not LowMemory and (S^.Status = stOk) then
  507.   begin
  508.     S^.Write(DSKSignature[1], SignatureLen);
  509.     StoreDesktop(S^);
  510.     StoreIndexes(S^);
  511.     StoreHistory(S^);
  512.     if S^.Status <> stOk then
  513.     begin
  514.       MessageBox('Could not create TVDEMO.DSK.', nil, mfOkButton + mfError);
  515.       {$I-}
  516.       Dispose(S, Done);
  517.       Assign(F, 'TVDEMO.DSK');
  518.       Erase(F);
  519.       Exit;
  520.     end;
  521.   end;
  522.   Dispose(S, Done);
  523. end;
  524.  
  525. procedure FileNew;
  526. begin
  527.   OpenEditor('', True);
  528. end;
  529.  
  530. procedure ShowClip;
  531. begin
  532.   ClipWindow^.Select;
  533.   ClipWindow^.Show;
  534. end;
  535.  
  536. begin
  537.   inherited HandleEvent(Event);
  538.   case Event.What of
  539.     evCommand:
  540.       begin
  541.         case Event.Command of
  542.           cmOpen: FileOpen('*.*');
  543.           cmNew: FileNew;
  544.           cmShowClip: ShowClip;
  545.           cmChangeDir: ChangeDir;
  546.           cmAbout: About;
  547.           cmPuzzle: Puzzle;
  548.           cmCalendar: Calendar;
  549.           cmAsciiTab: AsciiTab;
  550.           cmCalculator: Calculator;
  551.           cmColors: Colors;
  552.           cmMouse: Mouse;
  553.           cmSaveDesktop: SaveDesktop;
  554.           cmRetrieveDesktop: RetrieveDesktop;
  555.           cmStyx: OpenStyx;                      { ** TVGRAPH ** }
  556.         else
  557.           Exit;
  558.         end;
  559.         ClearEvent(Event);
  560.       end;
  561.   end;
  562. end;
  563.  
  564. procedure TTVDemo.Idle;
  565.  
  566. function IsTileable(P: PView): Boolean; far;
  567. begin
  568.   IsTileable := (P^.Options and ofTileable <> 0) and
  569.     (P^.State and sfVisible <> 0);
  570. end;
  571.  
  572. begin
  573.   inherited Idle;
  574.   Clock^.Update;
  575.   Heap^.Update;
  576.  
  577.   if Desktop^.FirstThat(@IsTileable) <> nil then
  578.     EnableCommands([cmTile, cmCascade])
  579.   else
  580.     DisableCommands([cmTile, cmCascade]);
  581. end;
  582.  
  583. procedure TTVDemo.InitMenuBar;
  584. var
  585.   R: TRect;
  586. begin
  587.   GetExtent(R);
  588.   R.B.Y := R.A.Y+1;
  589.   MenuBar := New(PMenuBar, Init(R, NewMenu(
  590.     NewSubMenu('~'#240'~', hcSystem, NewMenu(
  591.       NewItem('~A~bout', '', kbNoKey, cmAbout, hcSAbout,
  592.       NewLine(
  593.       NewItem('~P~uzzle', '', kbNoKey, cmPuzzle, hcSPuzzle,
  594.       NewItem('Ca~l~endar', '', kbNoKey, cmCalendar, hcSCalendar,
  595.       NewItem('Ascii ~t~able', '', kbNoKey, cmAsciiTab, hcSAsciiTable,
  596.       NewItem('~S~tyx', '', kbNoKey, cmStyx, hcNoContext,      { ** TVGRAPH ** }
  597.       NewItem('~C~alculator', '', kbNoKey, cmCalculator, hcCalculator, nil)))))))),
  598.     NewSubMenu('~F~ile', hcFile, NewMenu(
  599.       StdFileMenuItems(nil)),
  600.     NewSubMenu('~E~dit', hcEdit, NewMenu(
  601.       StdEditMenuItems(
  602.       NewLine(
  603.       NewItem('~S~how clipboard', '', kbNoKey, cmShowClip, hcShowClip,
  604.       nil)))),
  605.     NewSubMenu('~S~earch', hcSearch, NewMenu(
  606.       NewItem('~F~ind...', '', kbNoKey, cmFind, hcFind,
  607.       NewItem('~R~eplace...', '', kbNoKey, cmReplace, hcReplace,
  608.       NewItem('~S~earch again', '', kbNoKey, cmSearchAgain, hcSearchAgain,
  609.       nil)))),
  610.     NewSubMenu('~W~indow', hcWindows, NewMenu(
  611.       StdWindowMenuItems(nil)),
  612.     NewSubMenu('~O~ptions', hcOptions, NewMenu(
  613.       NewItem('~M~ouse...', '', kbNoKey, cmMouse, hcOMouse,
  614.       NewItem('~C~olors...', '', kbNoKey, cmColors, hcOColors,
  615.       NewLine(
  616.       NewItem('~S~ave desktop', '', kbNoKey, cmSaveDesktop, hcOSaveDesktop,
  617.       NewItem('~R~etrieve desktop', '', kbNoKey, cmRetrieveDesktop, hcORestoreDesktop, nil)))))),
  618.       nil)))))))));
  619. end;
  620.  
  621. procedure TTVDemo.InitStatusLine;
  622. var
  623.   R: TRect;
  624. begin
  625.   GetExtent(R);
  626.   R.A.Y := R.B.Y - 1;
  627.   StatusLine := New(PStatusLine, Init(R,
  628.     NewStatusDef(0, $FFFF,
  629.       NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit,
  630.       NewStatusKey('~F1~ Help', kbF1, cmHelp,
  631.       NewStatusKey('~F3~ Open', kbF3, cmOpen,
  632.       NewStatusKey('~Alt-F3~ Close', kbAltF3, cmClose,
  633.       NewStatusKey('~F5~ Zoom', kbF5, cmZoom,
  634.       NewStatusKey('', kbF10, cmMenu,
  635.       NewStatusKey('', kbCtrlF5, cmResize,
  636.       nil))))))),
  637.     nil)));
  638. end;
  639.  
  640. procedure TTVDemo.OutOfMemory;
  641. begin
  642.   MessageBox('Not enough memory available to complete operation.',
  643.     nil, mfError + mfOkButton);
  644. end;
  645.  
  646. { Since the safety pool is only large enough to guarantee that allocating
  647.   a window will not run out of memory, loading the entire desktop without
  648.   checking LowMemory could cause a heap error.  This means that each
  649.   window should be read individually, instead of using Desktop's Load.
  650. }
  651.  
  652. procedure TTVDemo.LoadDesktop(var S: TStream);
  653. var
  654.   P: PView;
  655.   Pal: PString;
  656.  
  657. procedure CloseView(P: PView); far;
  658. begin
  659.   Message(P, evCommand, cmClose, nil);
  660. end;
  661.  
  662. begin
  663.   if Desktop^.Valid(cmClose) then
  664.   begin
  665.     Desktop^.ForEach(@CloseView); { Clear the desktop }
  666.     repeat
  667.       P := PView(S.Get);
  668.       Desktop^.InsertBefore(ValidView(P), Desktop^.Last);
  669.     until P = nil;
  670.     Pal := S.ReadStr;
  671.     if Pal <> nil then
  672.     begin
  673.       Application^.GetPalette^ := Pal^;
  674.       DoneMemory;
  675.       Application^.ReDraw;
  676.       DisposeStr(Pal);
  677.     end;
  678.   end;
  679. end;
  680.  
  681. procedure TTVDemo.StoreDesktop(var S: TStream);
  682. var
  683.   Pal: PString;
  684.  
  685. procedure WriteView(P: PView); far;
  686. begin
  687.   if P <> Desktop^.Last then S.Put(P);
  688. end;
  689.  
  690. begin
  691.   Desktop^.ForEach(@WriteView);
  692.   S.Put(nil);
  693.   Pal := @Application^.GetPalette^;
  694.   S.WriteStr(Pal);
  695. end;
  696.  
  697.  
  698. var
  699.   Demo: TTVDemo;
  700.  
  701. begin
  702.   Demo.Init;
  703.   Demo.Run;
  704.   Demo.Done;
  705. end.
  706.